/*
 * Created on Aug 22, 2010 by Eng. Julian Rousselot
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package ar.com.visualAORE.model;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import ar.com.visualAORE.exceptions.SaveDocumentsLayersException;
import ar.com.visualAORE.exceptions.SelectionNotFoundException;
import ar.com.visualAORE.framework.model.Model;
import ar.com.visualAORE.util.Diff;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * @author julian
 *
 */
public class ModelVisualAORE extends Model {
	private Hashtable<String, Document> documents;
	private static ModelVisualAORE modelVisualAORE;
	private List<Concern> concerns;

	private ModelVisualAORE() {
		super();
		this.documents = new Hashtable<String,Document>();
		this.concerns = new ArrayList<Concern>();
	}
	public void addConcern(Concern concern){
		if(!concerns.contains(concern)){
			concerns.add(concern);
			setChanged();
			notifyObservers();
		}
		System.out.println(concerns.size());
	}
	/**
	 * Agrega todos los concerns que vienen de un documento
	 * @param concerns
	 */
	public void addConcerns(Set<Concern> concerns){
		Iterator<Concern> it = concerns.iterator();
		Concern concern = null;
		while(it.hasNext()){
			concern = it.next();
			this.addConcern(concern);
		}
	}
	/**
	 * Agrega una nueva selección a la colección
	 * @param selection
	 * @param key
	 */
	public void addSelection(Selection selection, String key){
		Document document = documents.get(key);
		document.addDocumentSelection(selection);
		System.out.println("DOC en el MODELO: " + documents);
	}
	/**
	 * Elimina una selección de la colección
	 * @param selection
	 * @param key
	 */
	public void removeSelection(Selection selection, String key){
		Document document = findDocument(key);
		document.removeDocumentSelection(selection);
	}
	/**
	 * busca una selección de la colección
	 * @param dot
	 * @param key
	 */
	public Selection getSelection(int dot, String key) throws SelectionNotFoundException{
		Document document = findDocument(key);
		Selection selection;
		boolean finded = false;
		Iterator<Selection> it = document.getSelections().iterator();
		while(it.hasNext()){
			selection = it.next();
			if((dot >= selection.getDot()) && (dot <= selection.getMark())){
				finded = true;
				return selection;
			}
			else
				throw new SelectionNotFoundException();
				
		}
		return null ;
	}
	/**
	 * Guarda todos los documentos
	 */
	public void saveDocumentsLayers() throws SaveDocumentsLayersException{
		XStream xstream = new XStream();
		xstream.alias("document", Document.class);
		
		Enumeration<String> e = documents.keys();
		String key;
		Document document;
		while (e.hasMoreElements()) {
			key = e.nextElement();
			document = documents.get(key);
			File file = new File(document.getPath().concat(".xml"));
			try {
				BufferedWriter bw = new BufferedWriter(new FileWriter(file));
				String xml = xstream.toXML(document);
				bw.write(xml);
				bw.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				throw new SaveDocumentsLayersException();
			}
		}
		System.out.println("DOCUMENTS: " + documents);
	}
	/**
	 * Guarda una copia del arvhivo original para controlar la version
	 */
	public void saveVersionControlFile(String aPathToOriginFile, String aVersionFile){
		
	}
	public String diff(String aldFilePath, String newFilePath){
		Diff d = new Diff();
		return d.doDiff(aldFilePath, newFilePath);
	}
	/**
	 * Carga un documento layer en la coleccion de documentos
	 * @param path
	 */
	public Document openDocument(String path){
		Document document = null;
		//XStream xstream = new XStream();
		XStream xstream = new XStream(new DomDriver()); 
		xstream.alias("document", Document.class);
		File file = new File(path);
		try {
			String sCurrentLine;
			BufferedReader br = new BufferedReader(new FileReader(file));
			String xml = "";
			
			while ((sCurrentLine = br.readLine()) != null) {
			    xml = xml.concat(sCurrentLine);  
			 } 
			System.out.println("XML: " + xml);
			document = (Document)xstream.fromXML(xml);
		} catch (FileNotFoundException e) {
		      e.printStackTrace();
		} catch (IOException e) {
		      e.printStackTrace();
	    }
		this.addDocument(document);
		this.addConcerns(document.getAllConcerns());
		return document;
	}
	public static ModelVisualAORE getInstance(){
		if(modelVisualAORE == null)
			modelVisualAORE = new ModelVisualAORE();
		return modelVisualAORE;
	}
	/**
	 * Busca un documento mediante su nombre
	 * @param key
	 * @return el documento buscado
	 */
	public Document findDocument(String key){
		return documents.get(key);
	}
	
	public void addDocument(Document document){
		this.documents.put(document.getName(), document);
	}
	public List<Concern> getConcerns() {
		return concerns;
	}
	public void setConcerns(List<Concern> concerns) {
		this.concerns = concerns;
	}
	
}
